package net.ib.mtalk.network.task;

import java.util.UUID;

import net.ib.mntalk.protocol.Common;
import net.ib.mntalk.protocol.Common.UUIDSliceRange;
import net.ib.mntalk.protocol.Session.GetReadMarksReq;
import net.ib.mntalk.protocol.Session.SendMessageReq;
import net.ib.mntalk.protocol.Session.SendMessageRes;
import net.ib.mtalk.constant.HandlerMsgConst;
import net.ib.mtalk.database.DatabaseContract.MessageTable.MessageStatus;
import net.ib.mtalk.database.helper.ChatDatabaseHelper;
import net.ib.mtalk.database.helper.InboxDatabaseHelper;
import net.ib.mtalk.global.GlobalPreferences;
import net.ib.mtalk.network.MethodId.Session;
import net.ib.mtalk.network.TcpEnvelope;
import net.ib.mtalk.util.GpbSupport;
import net.ib.mtalk.util.MTalkLogWriter;
import net.ib.mtalk.util.TimeAdapter;
import android.content.Context;
import android.os.Handler;
import android.util.Log;

/**
 * COMMENT : 미리 만들어진 SendMessageReq를 받아서 서버에 전송한다.<br>
 * PRE-EXECUTE : 1. SendMessageReq를 Insert한다(mRequstId를 받아서 request field에 세팅한다)<br>
 *   2. 실제 전송한다.<br>
 * POST-EXECUTE : 성공하면 성공Flag와 msgUuid로 데이터를 Update한다.<br>
 *   실패하면 실패Flag로 Update한다(아직 msgUuid가 없다)<br>
 *   전송하기 전 Insert 시에 사용한 requestId는 -1로 다시 반환한다<br>
 * @author eugenel, happy2v
 *
 */
public class SendMessageTask extends AsyncNetTask {
	
	protected SendMessageReq mSendMessageReq;
	protected long mClientViewUuidMsb;
	protected long mClientViewUuidLsb;
	private UUID mClientMsgUuid;
	
	public SendMessageTask(Context context, Handler handler) {
		super(context, handler);
	}
	
	/**
	 * @param context
	 * @param handler - UI에서 사용할 Handler
	 * @param sendMessageReq - ChatListActivity의 onSend()에서 Component들의 상태로 SendMessageReq를 만들어서 세팅한다
	 * @see net.ib.mtalk.ui.ChatListActivity#onSend
	 */
	public SendMessageTask(Context context, Handler handler, SendMessageReq sendMessageReq, long clientViewUuidMsb, long clientViewUuidLsb, UUID clientMsgUuid) {
		super(context, handler);
		setArguments(sendMessageReq, clientViewUuidMsb, clientViewUuidLsb, clientMsgUuid);
	}
	public SendMessageTask(Context context, Handler handler, SendMessageReq sendMessageReq, UUID clientUuid, UUID clientMsgUuid) {
		super(context, handler);
		setArguments(sendMessageReq, clientUuid, clientMsgUuid);
	}
	
	protected void setArguments(SendMessageReq sendMessageReq, long clientViewUuidMsb, long clientViewUuidLsb, UUID clientMsgUuid) {
		this.mSendMessageReq = sendMessageReq;
		this.mClientViewUuidMsb = clientViewUuidMsb;
		this.mClientViewUuidLsb = clientViewUuidLsb;
		this.mClientMsgUuid = clientMsgUuid;
	}
	
	protected void setArguments(SendMessageReq sendMessageReq, UUID clientUuid, UUID clientMsgUuid) {
		this.mSendMessageReq = sendMessageReq;
		this.mClientViewUuidMsb = clientUuid.getMostSignificantBits();
		this.mClientViewUuidLsb = clientUuid.getLeastSignificantBits();
		this.mClientMsgUuid = clientMsgUuid;
	}

	@Override
	protected TcpEnvelope onPreExecute() {
		TcpEnvelope rev = new TcpEnvelope.Builder()
			.setType(TcpEnvelope.REQUEST)
			.setMessage(mSendMessageReq)
			.setMethodId(Session.Messaging.SendMessage)
			.setExpireTime(5*TimeAdapter.TIME_SECOND)
			.build();
		return rev;
	}

	@Override
	protected void onPostExecute(int resultCode, Object requestObj, Object resultObj) {
		MTalkLogWriter.i("SendMessageTask.onPostExecute() resultCode :"+resultCode);
		if (resultObj == null) {
			if (mUiHandler != null) {
				mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_UNKNOWN_ERROR));
			}
			ChatDatabaseHelper.updateSendAfter(mContext, mClientMsgUuid, MessageStatus.SERVER_RECEIVE_FAIL, null);
			return;
		}
		TcpEnvelope resultEnvelope = (TcpEnvelope) resultObj;
		SendMessageRes msgRes = (SendMessageRes) resultEnvelope.getMessage();
		MTalkLogWriter.i("SendMessageTask.onPostExecute() getResponseCode :"+msgRes.getResponseCode());
		if(msgRes.getResponseCode()==Common.SUCCESS){
			// SEND-3-1. UPDATE Message by resultId
			// 첨부 파일이 있을경우 SendMessage(UserMessage)를 업데이트 한다.
			if(mSendMessageReq.getMessage().hasAttachFile() || mSendMessageReq.getMessage().hasAttachment()){
				ChatDatabaseHelper.setUserMessage(mContext, mClientMsgUuid, mSendMessageReq.getMessage()); 
			}
			
			ChatDatabaseHelper.updateSendAfter(mContext, mClientMsgUuid, msgRes);
			InboxDatabaseHelper.updateViewEnable(mContext, mClientViewUuidMsb, mClientViewUuidLsb, 1);
			if (mUiHandler != null) {
				mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_SEND_MESSAGE_SUCCESS));
			}
			
			if(InboxDatabaseHelper.getViewUUID(mContext, mClientViewUuidMsb, mClientViewUuidLsb) == null){
				return;
			}
			
			Log.w("ReadMark", "SendUUID : " + mClientMsgUuid.toString());
			UUIDSliceRange range = new UUIDSliceRange();
			range.setAscending(true);
			range.setMaxCount(20);
			range.setStart(GlobalPreferences.getLastReadmarkReceivedNotiUuid());
//			range.setEnd(GlobalPreferences.getLastReadmarkReceivedNotiUuid());
			
			GetReadMarksReq getReadMarksReq = new GetReadMarksReq();
			getReadMarksReq.setViewUuid(InboxDatabaseHelper.getViewUUID(mContext, mClientViewUuidMsb, mClientViewUuidLsb));
			getReadMarksReq.setRange(range);
			
			GetReadMarksTask getReadMarksTask = new GetReadMarksTask(mContext, mUiHandler, getReadMarksReq);
			getReadMarksTask.execute();
		} else if(msgRes.getResponseCode()==Common.NOT_EXIST_OBJECT){
			// SEND-3-2. NOT EXIST OBJECT
			ChatDatabaseHelper.updateSendAfter(mContext, mClientMsgUuid, MessageStatus.SERVER_RECEIVE_FAIL, msgRes);
		} else {
			// SEND-3-3. FAIL TO SEND
			ChatDatabaseHelper.updateSendAfter(mContext, mClientMsgUuid, MessageStatus.SERVER_RECEIVE_FAIL, msgRes);
			if (mUiHandler != null) {
				mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_SEND_MESSAGE_FAIL));
			}
		}
	}
}
